package com.epam.productxslt.command;


import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import com.epam.productxslt.controller.RequestContent;
import com.epam.productxslt.exception.ProductException;
import com.epam.productxslt.transformation.StylesheetCache;

import com.epam.productxslt.validation.ValidationRule;
import com.epam.productxslt.validation.rules.DateRule;
import com.epam.productxslt.validation.rules.ModelRule;
import com.epam.productxslt.validation.rules.NotEmptyValueRule;
import com.epam.productxslt.validation.rules.PriceRule;
import com.epam.productxslt.validation.validator.FormValidator;

public final class SaveGoodsCommand implements Command {
	private static final String VALIDATOR_NAME_PARAMETER = "formValidator";
	private static final String GOODS_REDIRECT_PATH = "controller?command=goods&categoryName=%s&subCategoryName=%s";
	@Override
	public void execute(RequestContent requestContent) throws ProductException {
		FormValidator validator = new FormValidator();
		
		ValidationRule notEmptyRule = new NotEmptyValueRule();
		ValidationRule modelRule = new ModelRule();
		ValidationRule priceRule = new PriceRule();
		ValidationRule dateRule = new DateRule();
		
		validator.addValidationRule(PRODUCER_NAME_PARAMETER, notEmptyRule);
		validator.addValidationRule(MODEL_NAME_PARAMETER, notEmptyRule);
		validator.addValidationRule(MODEL_NAME_PARAMETER, modelRule);
		validator.addValidationRule(DATE_NAME_PARAMETER, notEmptyRule);
		validator.addValidationRule(DATE_NAME_PARAMETER, dateRule);
		validator.addValidationRule(COLOR_NAME_PARAMETER, notEmptyRule);
		validator.addValidationRule(PRICE_NAME_PARAMETER, notEmptyRule);
		validator.addValidationRule(PRICE_NAME_PARAMETER, priceRule);

		try {
			Transformer transformer = StylesheetCache.newTransformer(RequestContent.SAVE_GOODS_XSL_PATH);
	
			transformer.setParameter(VALIDATOR_NAME_PARAMETER, validator);
			transformer.setParameter(PRODUCER_NAME_PARAMETER, requestContent.getRequestParameter(PRODUCER_NAME_PARAMETER));
			transformer.setParameter(MODEL_NAME_PARAMETER, requestContent.getRequestParameter(MODEL_NAME_PARAMETER));
			transformer.setParameter(DATE_NAME_PARAMETER, requestContent.getRequestParameter(DATE_NAME_PARAMETER));
			transformer.setParameter(COLOR_NAME_PARAMETER, requestContent.getRequestParameter(COLOR_NAME_PARAMETER));			
			if( requestContent.getRequestParameter(NOTINSTOCK_NAME_PARAMETER) != null){
				transformer.setParameter(NOTINSTOCK_NAME_PARAMETER, true);
			} else {
				transformer.setParameter(PRICE_NAME_PARAMETER, requestContent.getRequestParameter(PRICE_NAME_PARAMETER));
			}
			
			transformer.setParameter(CATEGORY_NAME_PARAMETER, requestContent.getRequestParameter(CATEGORY_NAME_PARAMETER));
			transformer.setParameter(SUBCATEGORY_NAME_PARAMETER, requestContent.getRequestParameter(SUBCATEGORY_NAME_PARAMETER));

			Writer tempWriter = new StringWriter();
			long xmlLastModified;
			File productXML;
			lock.readLock().lock();
			try{
				productXML= new File(RequestContent.XML_PATH);
				xmlLastModified = productXML.lastModified();
				transformer.transform(new StreamSource(RequestContent.XML_PATH), new StreamResult(tempWriter));
			} finally {
				lock.readLock().unlock();
			}
			if(validator.isValidForm()){
				Writer fileWriter;
				lock.writeLock().lock();
				try{
					if(xmlLastModified != productXML.lastModified()){
						tempWriter = new StringWriter();
						transformer.transform(new StreamSource(RequestContent.XML_PATH), new StreamResult(tempWriter));						
					}
					fileWriter = new FileWriter(RequestContent.XML_PATH);
					fileWriter.write(tempWriter.toString());
					fileWriter.close();
				} finally {
					lock.writeLock().unlock();
				}
				requestContent.setRedirectPath(String.format(GOODS_REDIRECT_PATH,
												requestContent.getRequestParameter(CATEGORY_NAME_PARAMETER),
												requestContent.getRequestParameter(SUBCATEGORY_NAME_PARAMETER)));
			}else {		
				requestContent.getResponseWriter().write(tempWriter.toString());
			}
		} catch (TransformerException | IOException e) {
			throw new ProductException(e);
		} 
	}
}
